{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Urban POMDP"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Method definition info(Any...) in module Base at util.jl:532 overwritten in module Logging at /mnt/c/Users/Maxime/wsl/.julia/v0.6/Logging/src/Logging.jl:115.\n",
      "WARNING: Method definition warn(Any...) in module Base at util.jl:585 overwritten in module Logging at /mnt/c/Users/Maxime/wsl/.julia/v0.6/Logging/src/Logging.jl:115.\n"
     ]
    }
   ],
   "source": [
    "using POMDPs, StatsBase, POMDPToolbox, RLInterface, Parameters, GridInterpolations\n",
    "using AutomotiveDrivingModels,AutoViz\n",
    "using Reel "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Method definition copyto!(Array{Float64, 1}, AutomotiveDrivingModels.LatLonAccel) in module AutomotiveDrivingModels at /mnt/c/Users/Maxime/wsl/.julia/v0.6/AutomotiveDrivingModels/src/2d/actions/lat_lon_accel.jl:13 overwritten in module AutoUrban at /mnt/c/Users/Maxime/wsl/.julia/v0.6/AutoUrban/src/simulation/actions.jl:10.\n",
      "WARNING: Method definition split_o(Array{Float64, 1}, AutomotivePOMDPs.UrbanPOMDP) in module AutomotivePOMDPs at /home/maxime/Maxime/OneDrive - Leland Stanford Junior University/Research/AutomotivePOMDPs/src/generative_pomdps/urban/generative_model.jl:559 overwritten at /home/maxime/Maxime/OneDrive - Leland Stanford Junior University/Research/AutomotivePOMDPs/src/decomposition/base_scenarios.jl:38.\n",
      "WARNING: Method definition #split_o(Array{Any, 1}, typeof(AutomotivePOMDPs.split_o), Array{Float64, 1}, AutomotivePOMDPs.UrbanPOMDP) in module AutomotivePOMDPs overwritten.\n"
     ]
    }
   ],
   "source": [
    "# include(\"AutomotivePOMDPs.jl\")\n",
    "using AutomotivePOMDPs\n",
    "using AutomotiveSensors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "rng = MersenneTwister(1);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "params = UrbanParams(nlanes_main=1,\n",
    "                     crosswalk_pos =[VecSE2(6, 0., pi/2), VecSE2(-6, 0., pi/2), VecSE2(0., -5., 0.)],\n",
    "                     crosswalk_length =  [14.0, 14., 14.0],\n",
    "                     crosswalk_width = [4.0, 4.0, 3.1],\n",
    "                     stop_line = 22.0)\n",
    "env = UrbanEnv(params=params);\n",
    "obs_dist = ObstacleDistribution(env)\n",
    "pomdp = UrbanPOMDP(env=env, \n",
    "                   sensor=PerfectSensor(),\n",
    "                   obs_dist=obs_dist,\n",
    "                   max_obstacles=1,\n",
    "                   max_peds=1,\n",
    "                   max_cars=5, \n",
    "                   ped_birth=0.1, \n",
    "                   ego_goal=LaneTag(2, 1));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "POMDPToolbox.FunctionPolicy(#3)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "policy = solve(RandomSolver(rng), pomdp)\n",
    "up = updater(policy);\n",
    "policy = FunctionPolicy(s->UrbanAction(0.0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  0.045259 seconds (186.84 k allocations: 5.614 MiB, 33.33% gc time)\n"
     ]
    }
   ],
   "source": [
    "hr = HistoryRecorder(rng=rng, max_steps=20)\n",
    "@time hist = simulate(hr, pomdp, policy, up);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<video autoplay controls><source src=\"files/reel-2353082177546291485.webm?6614370586952560574\" type=\"video/webm\"></video>"
      ],
      "text/plain": [
       "Reel.Frames{MIME{Symbol(\"image/png\")}}(\"/tmp/tmph5qnMA\", 0x0000000000000015, 4.0, nothing)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "duration, fps, render_hist = animate_scenes(hist.state_hist, pomdp.env, overlays = SceneOverlay[IDOverlay()], sim_dt=pomdp.ΔT, cam=StaticCamera(VecE2(0.,-10.), 14.))\n",
    "speed_factor = 2.\n",
    "film = roll(render_hist, fps = speed_factor*fps, duration = duration/speed_factor)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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AMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAdOpcXAAACfBJREFUgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEAAAANILgDAAAAGkBwBwAAADSA4A4AAABoAMEdAAAA0ACCOwAAAKABBHcAAABAAwjuAAAAgAYQ3AEA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",
      "text/plain": [
       "Cairo.CairoSurface{UInt32}(Ptr{Void} @0x0000000005c1fa90, 1000.0, 600.0, #undef)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = obs_to_scene(pomdp, hist.observation_hist[end])\n",
    "AutoViz.render(s, env, [IDOverlay()], cam=FitToContentCamera(0.))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "ename": "LoadError",
     "evalue": "\u001b[91mUndefVarError: hist not defined\u001b[39m",
     "output_type": "error",
     "traceback": [
      "\u001b[91mUndefVarError: hist not defined\u001b[39m",
      "",
      "Stacktrace:",
      " [1] \u001b[1manonymous\u001b[22m\u001b[22m at \u001b[1m./<missing>:?\u001b[22m\u001b[22m",
      " [2] \u001b[1minclude_string\u001b[22m\u001b[22m\u001b[1m(\u001b[22m\u001b[22m::String, ::String\u001b[1m)\u001b[22m\u001b[22m at \u001b[1m./loading.jl:522\u001b[22m\u001b[22m"
     ]
    }
   ],
   "source": [
    "for veh in hist.state_hist[20]\n",
    "    println(veh)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Fast evaluation\n",
    "probs = 0.:0.1:1.0\n",
    "crash_array = zeros(length(probs))\n",
    "for (j,prob) in enumerate(probs)\n",
    "    pomdp.ped_birth = prob\n",
    "    n_eval = 1000\n",
    "    crashes, time_outs, successes = 0, 0, 0\n",
    "#     sim = RolloutSimulator(rng=rng, max_steps=100)\n",
    "    for i=1:n_eval\n",
    "        hr = HistoryRecorder(rng=rng, max_steps=100)\n",
    "        hist = simulate(hr, pomdp, policy, up)\n",
    "        r_tot = discounted_reward(hist)\n",
    "        if r_tot < 0.\n",
    "            crashes += 1\n",
    "        elseif r_tot == 0.\n",
    "            time_outs += 1\n",
    "            return\n",
    "        else \n",
    "            successes += 1\n",
    "        end\n",
    "    end\n",
    "    crash_array[j] = crashes\n",
    "    println(\"Crashes : \", crashes/10, \" Successes \", successes/10, \" Time outs \", time_outs/10)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "lane = rand(rng, get_lanes(pomdp.env.roadway))\n",
    "route = random_route(rng, pomdp.env.roadway, lane)\n",
    "for l in route\n",
    "    println(l.tag)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "conflict_lanes = get_conflict_lanes(pomdp.env.crosswalks[3], pomdp.env.roadway)\n",
    "for l in conflict_lanes\n",
    "    println(l.tag)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "intersect(conflict_lanes, route)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "AutoViz.render(initialstate(pomdp, rng, true), env, [IDOverlay()], cam=FitToContentCamera(0.))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "n_steps = 100\n",
    "scenes = Scene[]\n",
    "pomdp.ped_birth = 0.5\n",
    "s = initialstate(pomdp, rng)\n",
    "push!(scenes, s)\n",
    "for step=1:n_steps\n",
    "    sp = generate_s(pomdp, s, UrbanAction(0.), rng)\n",
    "    s = sp\n",
    "    push!(scenes, s)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "duration, fps, render_hist = animate_scenes(scenes, pomdp.env, overlays = SceneOverlay[IDOverlay()], sim_dt=pomdp.ΔT)\n",
    "speed_factor = 2.\n",
    "film = roll(render_hist, fps = speed_factor*fps, duration = duration/speed_factor)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "pomdp.models[7].intersection_driver"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "function initial_pedestrian(pomdp::UrbanPOMDP, scene::Scene, rng::AbstractRNG, first_scene::Bool = false)\n",
    "    env = pomdp.env\n",
    "    crosswalk_pos = env.params.crosswalk_pos\n",
    "\n",
    "    # position along the crosswalk\n",
    "    t0 = rand(rng, Uniform(-env.params.crosswalk_width/2, env.params.crosswalk_width/2))\n",
    "    s0 = rand(rng, [0., get_end(env.crosswalk)])\n",
    "    ϕ0 = float(π)\n",
    "    if s0 == 0.\n",
    "        ϕ0 = 0.\n",
    "    end\n",
    "    if first_scene\n",
    "        s0 = rand(rng, Uniform(0., get_end(env.crosswalk)))\n",
    "    end\n",
    "\n",
    "    #velocity\n",
    "    v0 = rand(rng, Uniform(0., env.params.ped_max_speed))\n",
    "    posF = Frenet(env.crosswalk, s0, t0, ϕ0)\n",
    "\n",
    "    ped_initialstate = VehicleState(posF, env.roadway, v0);\n",
    "\n",
    "    # new id, increment last id\n",
    "    max_id = 0\n",
    "    for veh in scene\n",
    "        if veh.id > max_id\n",
    "            max_id = veh.id\n",
    "        end\n",
    "    end\n",
    "    id = max_id + 1\n",
    "    if max_id == 0\n",
    "        id = 2\n",
    "    end\n",
    "\n",
    "\n",
    "    return Vehicle(ped_initialstate, AutomotivePOMDPs.PEDESTRIAN_DEF, id)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "scene = Scene()\n",
    "models = Dict{Int, DriverModel}()\n",
    "for i=1:5\n",
    "    ped = initial_pedestrian(pomdp, scene, rng, true)\n",
    "    push!(scene, ped)\n",
    "    models[ped.id] = ConstantPedestrian()\n",
    "end\n",
    "# car = initial_car(pomdp, scene, rng)\n",
    "# collision point 7.0, 4.5\n",
    "car = Vehicle(VehicleState(Frenet(env.roadway[LaneTag(3,1)], 0.), env.roadway, 6.), VehicleDef(), 1)\n",
    "push!(scene, car);\n",
    "AutoViz.render(scene, env, cam=FitToContentCamera(0.))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "timestep = 0.5\n",
    "\n",
    "lane = get_lane(pomdp.env.roadway, car)\n",
    "route = random_route(rng, pomdp.env.roadway, lane)\n",
    "intersection_entrances = get_start_lanes(pomdp.env.roadway)\n",
    "if !(route[1] ∈ intersection_entrances)\n",
    "    intersection = Lane[]\n",
    "    intersection_exits = Lane[]\n",
    "else\n",
    "    intersection_exits = get_exit_lanes(pomdp.env.roadway)\n",
    "    intersection=Lane[route[1], route[2]]\n",
    "end\n",
    "navigator = RouteFollowingIDM(route=route)\n",
    "intersection_driver = StopIntersectionDriver(navigator= navigator,\n",
    "#                                                        intersection=intersection,\n",
    "                                                       intersection_entrances = intersection_entrances,\n",
    "                                                       intersection_exits = intersection_exits,\n",
    "                                                       stop_delta=0.,\n",
    "                                                       accel_tol=0.)\n",
    "cw_conflict_lanes = get_conflict_lanes(pomdp.env.crosswalk, pomdp.env.roadway)\n",
    "crosswalk_driver = CrosswalkDriver(navigator = navigator,\n",
    "                                   crosswalk = pomdp.env.crosswalk,\n",
    "                                   conflict_lanes = cw_conflict_lanes,\n",
    "                                   intersection_entrances = intersection_entrances,\n",
    "                                   yield=!isempty(intersect(cw_conflict_lanes, route)),\n",
    "                                   debug=true)\n",
    "models[car.id] = UrbanDriver(navigator=navigator,\n",
    "                        intersection_driver=intersection_driver,\n",
    "                       crosswalk_driver=crosswalk_driver,\n",
    "                            debug=true           )\n",
    "\n",
    "nticks = 50\n",
    "rec = SceneRecord(nticks+1, timestep)\n",
    "@time simulate!(rec, scene, pomdp.env.roadway, models, nticks)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "cam = FitToContentCamera(0.)\n",
    "duration, fps, render_rec = animate_record(pomdp.env, rec, sim_dt=timestep, overlays = SceneOverlay[IDOverlay()])\n",
    "film = roll(render_rec, fps = fps, duration = duration)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "scene = initialstate(pomdp, rng)\n",
    "AutoViz.render(scene, env, [IDOverlay()], cam=FitToContentCamera(0.))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "function lane_to_segment(lane::Lane, roadway::Roadway)\n",
    "    # only works for straight lanes\n",
    "    lane_a = posg(Frenet(lane, 0.), roadway)\n",
    "    lane_b = posg(Frenet(lane, get_end(lane)), roadway)\n",
    "    return LineSegment(lane_a, lane_b)\n",
    "end\n",
    "\n",
    "function  get_conflict_lanes(crosswalk::Lane, roadway::Roadway)\n",
    "    # find lane intersecting with crosswalk \n",
    "    cw_seg = lane_to_segment(crosswalk, roadway)    \n",
    "    conflict_lanes = Lane[]\n",
    "    lanes = get_lanes(roadway)\n",
    "    for lane in lanes\n",
    "        lane_seg = lane_to_segment(lane, roadway)\n",
    "        if intersects(lane_seg, cw_seg) && !(lane ∈ conflict_lanes)\n",
    "            push!(conflict_lanes, lane)\n",
    "        end\n",
    "    end\n",
    "    return conflict_lanes\n",
    "end\n",
    "\n",
    "# return +1 if going toward, -1 if going away\n",
    "function direction_from_center(ped::Vehicle, crosswalk::Lane)\n",
    "    s_ped = ped.state.posF.s\n",
    "    Δs = get_end(crosswalk)/2 - s_ped\n",
    "    return sign(Δs*cos(ped.state.posF.ϕ))\n",
    "end\n",
    "\n",
    "function is_crossing(ped::Vehicle, crosswalk::Lane, conflict_lanes::Vector{Lane})\n",
    "    # check if the pedestrian is in the conflict zone\n",
    "    for lane in conflict_lanes\n",
    "        ped_f = Frenet(ped.state.posG, lane, roadway)\n",
    "        if abs(ped_f.t) < lane.width/2\n",
    "            return true\n",
    "        end\n",
    "    end\n",
    "    # at this point, the pedestrian is not on the road\n",
    "    # check if she is going to cross or not\n",
    "    if direction_from_center(ped, crosswalk) > 0.\n",
    "        return true\n",
    "    end\n",
    "    return false\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# given crosswalk compute the \"conflict zone\"\n",
    "crosswalk = env.crosswalk\n",
    "conflict_lanes = get_conflict_lanes(crosswalk, env.roadway)\n",
    "\n",
    "ped = scene[findfirst(scene, 5)]\n",
    "is_crossing(ped, crosswalk, conflict_lanes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "function get_stop_zone(crosswalk::Lane, roadway::Roadway)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "length(conflict_lanes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "lane_seg = lane_to_segment(lanes[3], roadway)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "methods(get_posG)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "roadway = env.roadway\n",
    "veh = scene[findfirst(scene, 8)]\n",
    "lane = get_lane(roadway, veh)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "methods(Frenet)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "function is_in_lane(veh::Vehicle, lane::Lane, roadway::Roadway)\n",
    "    pos_g = veh.state.posG\n",
    "    proj(pos_g, lane)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "methods(proj)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "using Interact\n",
    "\n",
    "scene = Scene()\n",
    "\n",
    "type LaneOverlay <: SceneOverlay\n",
    "    lane::Lane\n",
    "    color::Colorant\n",
    "end\n",
    "function AutoViz.render!(rendermodel::RenderModel, overlay::LaneOverlay, scene::Scene, roadway::Roadway)\n",
    "    render!(rendermodel, overlay.lane, roadway, color_asphalt=overlay.color)\n",
    "    return rendermodel\n",
    "end\n",
    "\n",
    "# @manipulate for i in 1 : length(env.roadway.segments)\n",
    "#     AutoViz.render(scene, env.roadway, [LaneOverlay(env.roadway[LaneTag(i,1)], RGBA(0.0,0.0,1.0,0.5))], cam=FitToContentCamera(0.))\n",
    "# end\n",
    "\n",
    "i=8\n",
    "AutoViz.render(scene, env.roadway, [LaneOverlay(env.roadway[LaneTag(i,1)], RGBA(0.0,0.0,1.0,0.5))], cam=FitToContentCamera(0.))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "env.roadway[LaneTag(1,1)].exits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "function is_straight(lane::Lane)\n",
    "end"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 0.6.1",
   "language": "julia",
   "name": "julia-0.6"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "0.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
